import 'dart:convert';

import 'package:dio/dio.dart' as Dio;
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:zootix/apis/zt-api.dart' as Api;
import 'package:zootix/store/zt_store.dart';
import 'package:zootix/util/zt_logger_util.dart';
import 'package:zootix/widgets/zt_tap_to_dismiss_keyboard.dart';
import 'package:zootix/zt_config.dart';
import 'package:zootix/models/zt_auth.dart';
import 'package:zootix/models/zt_user_info.model.dart';
import 'package:zootix/services/zt_service.dart';

import '../constants/zt_constants.dart';
import '../util/zt_util.dart';

class ZtAuthStore extends GetxController {
  static ZtAuthStore get to => Get.find();
  final userInfo = ZtUserInfoModel().obs;

  Future<ZtAuthStore> init() async {
    try {
      String? preUserInfo = ZtStorageService.to
          .getString(ZtCacheKeys.userInfo, isWithUser: false);
      String? token =
          ZtStorageService.to.getString(ZtCacheKeys.token, isWithUser: false);

      if (token != null) {
        final response = await Api.isValidToken(token);
        if (response.data != null) {
          // Token有效无需登录
          if (response.data['data'] == true) {
          } else {
            ZtLoggerUtil().info('[Store-Auth] Token invalid, need to login.');
            await ZtStorageService.to
                .remove(ZtCacheKeys.token, isWithUser: false);
          }
          if (preUserInfo != null) {
            userInfo(ZtUserInfoModel.fromJson(jsonDecode(preUserInfo)));
            ZtLoggerUtil()
                .info('[Store-Auth] userId: ${userInfo.value.userId}');
          }
        }
      }
    } catch (e) {
      ZtLoggerUtil().info(
        '[Store-Auth]Init failed, please try again.${e}',
      );
    }
    return this;
  }

  Future<void> deleteAccount() async {
    await ZtLoadingUtil.show(status: 'Deleting...');
    try {
      final response = await Api.deleteAccount();
      if (response.data != null) {
        ZtLogManger().putLog(
          ZtLogType.clickEvent,
          ZtLogManger.buildEvent(
              logType: ZtLogType.clickEvent, page: ZtLogPages.deleteaccount),
        );
        await ZtSnackBarUtil().success('Delete account succeed.');
        await logout();
      }
    } catch (e) {
      await ZtSnackBarUtil().error('Delete account faield. Please try again.');
    } finally {
      await EasyLoading.dismiss();
    }
  }

  Future<void> logout({bool force = false}) async {
    await ZtLoadingUtil.show(status: 'Logout...');
    await ZtStorageService.to.remove(ZtCacheKeys.token, isWithUser: false);
    await ZtStorageService.to.remove(ZtCacheKeys.userInfo, isWithUser: false);
    await ZtImChartStore.to.disconnectIM();
    await ZtImChartStore.to.imEngine?.destroy();
    try {
      final response = await Api.logout();
      if (response.data != null) {
        ZtLogManger().putLog(
          ZtLogType.clickEvent,
          ZtLogManger.buildEvent(
              logType: ZtLogType.clickEvent, page: ZtLogPages.logout),
        );
        ZtLoggerUtil().info('[Store-Auth] Logout succeed.');
        if (Get.context != null) Get.offAllNamed(ZtRouteConfig.login);
      }
    } catch (e) {
    } finally {
      ZtLoadingUtil.dismiss();
    }
  }

  Future<void> login(ZtLoginEnum type, {String? identityToken}) async {
    Dio.Response response;
    ZtLogManger().putLog(
      ZtLogType.globalBehavior,
      ZtLogManger.buildEvent(
          logType: ZtLogType.globalBehavior,
          page: type == ZtLoginEnum.fastLogin
              ? ZtLogPages.fastLogin
              : ZtLogPages.applelogin),
    );

    if (type == ZtLoginEnum.fastLogin &&
        ZtStorageService.to
                .getString(ZtCacheKeys.deviceUUID, isWithUser: false) ==
            null) {
      ZtSnackBarUtil().error('Need DeviceUUID. Please restart app.');
      return;
    }

    ZtLoadingUtil.show(status: 'Login...');
    // Hide keyboard
    TapToDismissKeyboard.dismissOf(context: Get.context!);
    try {
      response = await Api.login(
          '${type == ZtLoginEnum.fastLogin ? 4 : 3}',
          type == ZtLoginEnum.fastLogin
              ? (ZtStorageService.to
                  .getString(ZtCacheKeys.deviceUUID, isWithUser: false))
              : identityToken);

      if (response.data != null) {
        final auth = Auth.fromJson(response.data['data']);
        if (auth.token != null) {
          await ZtStorageService.to
              .setString(ZtCacheKeys.token, auth.token!, isWithUser: false);
        }
        if (auth.userInfo != null) {
          userInfo(auth.userInfo!);
          await ZtStorageService.to.setString(
              ZtCacheKeys.userInfo, jsonEncode(auth.userInfo),
              isWithUser: false);
          ZtLoggerUtil().info('[Store-Auth] Login succeed.');
          ZtLogManger().putLog(
            ZtLogType.globalBehavior,
            ZtLogManger.buildEvent(
                logType: ZtLogType.globalBehavior,
                page: ZtLogPages.loginsuccess),
          );
        }
        Get.offNamed(ZtRouteConfig.home);
        getCommonInfo();
      }
    } catch (e) {
      ZtSnackBarUtil().error('${e}');
    } finally {
      ZtLoadingUtil.dismiss();
    }
  }

  Future<void> updateUserInfoState(ZtUserInfoModel newInfo) async {
    userInfo(newInfo);
    await ZtStorageService.to.setString(
        ZtCacheKeys.userInfo, jsonEncode(newInfo),
        isWithUser: false);
  }

  Future<void> getUserInfo() async {
    await ZtLoadingUtil.show(status: 'Loading...');
    try {
      final response = await Api.getUserInfo(userInfo.value.userId!);
      if (response.data != null) {
        ZtUserInfoModel userInfo =
            ZtUserInfoModel.fromJson(response.data['data']);
        await updateUserInfoState(userInfo);
      }
    } catch (e) {
      ZtLoadingUtil.showError('$e');
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<void> saveUserInfo(Map<String, dynamic> data) async {
    ZtLoadingUtil.show(status: 'Saving...');
    try {
      final res = await Api.saveUserInfo(data);
      if (res.data != null) {
        await getUserInfo();
        ZtSnackBarUtil().success('Save successfully.');
      }
    } catch (e) {
      ZtSnackBarUtil().error('$e');
    } finally {
      EasyLoading.dismiss();
    }
  }

  Future<void> getCommonInfo() async {
    await ZtAppInfoService.to.getAppConfig();
    await Future.wait([
      /// 依赖注入票务信息
      Get.putAsync<ZtTicketStore>(() => ZtTicketStore().init()),

      /// 依赖注入IMChat
      Get.putAsync<ZtImChartStore>(() => ZtImChartStore().init()),

      /// 依赖注入拉黑屏蔽信息
      Get.putAsync<ZtBlockStore>(() => ZtBlockStore().init()),
      ZtAppInfoService.to.getossPolicy()
    ]);
  }
}
